home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 293_01 / ang1.c < prev    next >
C/C++ Source or Header  |  1989-08-23  |  22KB  |  759 lines

  1. /********************  ang.c  ******************************
  2.  
  3.    Three dimensional surface reconstruction program
  4.  
  5.    This program assumes that the views from the main axis
  6.    directions were done thus an angle view between two main
  7.    axis views can be created from the depth_code viewa(floating
  8.    point). 
  9.  
  10.  Daniel Geist
  11.  Michael W. Vannier
  12.  
  13.  Mallinckrodt Institute of Radiology
  14.  Washington University School of Medicine
  15.  510 S. Kingshighway Blvd.
  16.  St. Louis, Mo. 63110
  17.  
  18.  Note:  This program is intended for the private non-commercial
  19.  use of interested individuals to provide a fuller explanation of
  20.  the algorithms described in "Three dimensional reconstruction in
  21.  Medical Imaging" by D. Geist and M. Vannier.
  22.  
  23.  1988
  24.  
  25.  A.Wallin
  26.  -Command line input
  27.  -Threshold on gradient shading, background not used for gradient.
  28.  -Combination of gradient and distance is possible.
  29.  -Distance or gradient image turned off
  30.  -Straight views (0, 90, 180 etc) possible. (0 = ydis2.dat, 90 = xdis1.dat
  31.   180 = ydis1.dat, 270 = xdis2.dat)
  32.  -Incremental views possible
  33.  -Views always head up
  34.  *************************************************************/
  35.  
  36. #include <stdio.h>
  37. #include <math.h>
  38. #include <ctype.h>
  39. #define FLOAT_LINE 256*sizeof(float)
  40. #define PI 3.141592653
  41.  
  42. /* the structure below is the data for a point on the surface projected
  43.    on the view plane                        */
  44. typedef struct DIS_REC {
  45.       float dist;            /*distance from view plane */
  46.       int indXY;             /* index of data on main axis view */
  47.       char XY;               /* Which main axis view obtained from (X or Y)*/
  48. };
  49.  
  50. struct DIS_REC distances[256]; /* one projected line */
  51.  
  52. int NLINES,IXmax,IYmax,xinc,yinc;
  53. int (*xdir)(),(*ydir)();
  54. double THETA,cosTheta,sinTheta,tgnTheta;
  55. float fxbuf[3][256],fybuf[3][256];/* input buffers */
  56.  
  57. char *usestr = "Usage: ang [-a] [-r] [-g] [-n(d|g)] [-h] [-d]";
  58. float GRAD_THRESHOLD = 10.0;
  59. int  number_pic = 1;
  60. int  dispmode = 3;
  61. float dist_weight;
  62.  
  63. /*  output files  */
  64. char fng[13],fnd[13],xfile[13],yfile[13],DR;
  65.  
  66. succ(i)
  67. int i;
  68. {return(i==2?0:i+1);}
  69.  
  70. prev(i)
  71. int i;
  72. {return(i==0?2:i-1);}
  73.  
  74. forward(i)
  75. int i;
  76. { return(i); }
  77.  
  78. backward(i,start)
  79. int i;
  80. {return(start-i); }
  81.  
  82. /* PUTD - fill a DIS_REC with values */
  83. putd(pdis,D,i,xy_sym)
  84. struct DIS_REC *pdis;
  85. float D;
  86. int i,xy_sym;
  87.  
  88. { pdis->dist=D;
  89.   pdis->indXY=i;
  90.   pdis->XY=xy_sym;
  91. }
  92.  
  93. /* take one line from X and Y views and create a projrcted line */
  94. getdistances(linex,liney)
  95. float linex[],liney[];
  96.  
  97. { int i,IND,X,Y;
  98.   float D;
  99.   float Dhole;
  100.   float INDf;
  101.   int   holex, holey;
  102.   float dx1, dx2, dx;
  103.   float dy1, dy2, dy;
  104.   float temp1, temp2;
  105.  
  106.   for(i=0;i<256;i++) distances[i].XY=0;
  107.   /* project Y-data onto image line */
  108.   for(i=0;i<256;i++) if(liney[i] < 256.0){
  109.        X=(*ydir)(i,255);
  110.        INDf=IXmax -(X*sinTheta-liney[i]*cosTheta);
  111.        D=liney[i]/sinTheta+(X-liney[i]/tgnTheta)*cosTheta;
  112.        /*  Do the two nearest neighbours */
  113.        IND = INDf;
  114.        if((IND>=0) && (IND<256)){
  115.            if(distances[IND].XY==0)putd(&distances[IND],D,i,1);
  116.            else if(distances[IND].dist>D)putd(&distances[IND],D,i,1);
  117.        }
  118.        IND = INDf + 0.5;
  119.        if((IND>=0) && (IND<256)){
  120.            if(distances[IND].XY==0)putd(&distances[IND],D,i,1);
  121.            else if(distances[IND].dist>D)putd(&distances[IND],D,i,1);
  122.        }
  123.   }
  124.  
  125.   /*project X-data onto image plane */
  126.  for(i=0;i<256;i++) if(linex[i] < 256.0){
  127.        Y=(*xdir)(i,255);
  128.        D=Y/sinTheta+(linex[i]-Y/tgnTheta)*cosTheta;
  129.        INDf=IXmax-(linex[i]*sinTheta-Y*cosTheta);
  130.        /*  Do the two nearest neighbours */
  131.        IND = INDf;
  132.        if((IND>=0) && (IND<256)){
  133.            if(distances[IND].XY==0)putd(&distances[IND],D,i,2);
  134.            else if(distances[IND].dist>D)putd(&distances[IND],D,i,2);
  135.        }
  136.        IND = INDf + 0.5;
  137.        if((IND>=0) && (IND<256)){
  138.            if(distances[IND].XY==0)putd(&distances[IND],D,i,2);
  139.            else if(distances[IND].dist>D)putd(&distances[IND],D,i,2);
  140.        }
  141.   }
  142.  
  143.   /* fill holes due to low resolution */
  144.   if (dispmode & 4)
  145.     /* test neighbours */
  146.     for(i=1;i<255;i++)
  147.       if( (distances[i].XY==0) && (distances[i+1].XY!=0) &&
  148.             (distances[i-1].XY!=0))
  149.              putd(&distances[i],distances[i-1].dist,
  150.                    distances[i-1].indXY,(int)distances[i-1].XY);
  151.                    
  152. }
  153.  
  154. /* returns gradient shade in point given the variations of the surface */
  155. unsigned char grad(x1,x2,y1,y2,z1,z2,x_fac,y_fac,z_fac)
  156. float x1,x2,y1,y2,z1,z2;
  157. int x_fac,y_fac,z_fac;
  158. {float gx,gy,gz,G,nx,ny;
  159.  unsigned char gxint;
  160.      /* components of gradient */
  161.   gx=(x2-x1)/x_fac;
  162.   gy=(y2-y1)/y_fac;
  163.   gz=(z1-z2)/z_fac;
  164.   G=sqrt(gx*gx+gy*gy+gz*gz);
  165.      /*compute nx,ny normalized x,y component of gradient */
  166.   nx=gx/G;
  167.   ny=gy/G;
  168.   gxint=255*(nx*cosTheta+ny*sinTheta)+0.5; /*scale gradient shade by 256 */
  169.   return(gxint);
  170. }
  171.  
  172. doline(linex,linex1,linex2,liney,liney1,liney2,z_fac,fg,fd)
  173. float linex[],linex1[],linex2[],liney[],liney1[],liney2[];
  174. int z_fac;
  175. FILE *fg,*fd;
  176.  
  177. { int i;
  178.   unsigned char lined[256],lineg[256];
  179.   float x1, x2, y1, y2, z1, z2;
  180.   int   x_fac, y_fac;
  181.  
  182.       /* empty bit on image line */
  183.   for(i=0;i<256;i++)
  184.     if (distances[i].XY==0)
  185.       lineg[i]=lined[i]=0;
  186.     else {
  187.       if (dispmode & 1)
  188.         lined[i]=(distances[i].dist<256)?255-distances[i].dist+0.5:0;
  189.       /* bit on image line projected from Y view */
  190.       if (dispmode & 2) {
  191.         if(distances[i].XY==1) switch(distances[i].indXY){
  192.            case 0:
  193.              lineg[i]=
  194.                    grad(liney[1]*yinc,liney[0]*yinc,(float)0,(float)2,
  195.                         liney1[0],liney2[0],1,2,z_fac);
  196.              break;
  197.            case 255:
  198.              lineg[i]=
  199.                     grad(liney[255]*yinc,liney[254]*yinc,(float)0,(float)2,
  200.                          liney1[255],liney2[255],1,2,z_fac);
  201.              break;
  202.            default:
  203.              x1 = liney[distances[i].indXY+yinc];
  204.              x2 = liney[distances[i].indXY-yinc];
  205.              x_fac = 2;
  206.              y1 = 0.0;
  207.              y2 = 2.0;
  208.              y_fac = 2;
  209.              z1 = liney1[distances[i].indXY];
  210.              z2 = liney2[distances[i].indXY];
  211.              if (x1 > 255.0) {
  212.                x1 = liney[distances[i].indXY];
  213.                x_fac = 1;
  214.              }
  215.              else if (x2 > 255.0) {
  216.                x2 = liney[distances[i].indXY];
  217.                x_fac = 1;
  218.              }
  219.              else if (fabs(x2 - x1) > GRAD_THRESHOLD) {
  220.                if (fabs(liney[distances[i].indXY] - x1) < GRAD_THRESHOLD/2.0 &&
  221.                    x2 < liney[distances[i].indXY]) {
  222.                  x2 = liney[distances[i].indXY];
  223.                  x_fac = 1;
  224.                }
  225.                else if (fabs(x2 - liney[distances[i].indXY]) <
  226.                         GRAD_THRESHOLD/2.0 && x1 < liney[distances[i].indXY]) {
  227.                  x1 = liney[distances[i].indXY];
  228.                  x_fac = 1;
  229.                }
  230.              }
  231.              if (z1 > 255.0) {
  232.                z1 = liney[distances[i].indXY];
  233.                z_fac = 1;
  234.              }
  235.              else if (z2 > 255.0) {
  236.                z2 = liney[distances[i].indXY];
  237.                z_fac = 1;
  238.              }
  239.              else if (fabs(z2 - z1) > GRAD_THRESHOLD) {
  240.                if (fabs(liney[distances[i].indXY] - z1) < GRAD_THRESHOLD/2.0 &&
  241.                  z2 < liney[distances[i].indXY]) {
  242.                  z2 = liney[distances[i].indXY];
  243.                  z_fac = 1;
  244.                }
  245.                else if (fabs(z2 - liney[distances[i].indXY]) <
  246.                         GRAD_THRESHOLD/2.0 && z1 < liney[distances[i].indXY]) {
  247.                  z1 = liney[distances[i].indXY];
  248.                  z_fac = 1;
  249.                }
  250.              }
  251.              lineg[i]= grad(x1, x2, y1, y2, z1, z2, x_fac, y_fac, z_fac);
  252.              break;
  253.         }
  254.         /* bit on image line projected from X view */
  255.         else 
  256.           switch(distances[i].indXY){
  257.            case